// Ignore argument count for test functions.
#![allow(clippy::too_many_arguments)]

use ndarray::{array, Array2};
use rstest::rstest;

use crate::tests::fixtures::{
    rand_usize,
    random_missing_tile_policy,
    random_tile_selection_policy,
    random_tile_type,
    RANDOM_PREDECESSOR,
};
use crate::tiling::slot_grid::tests::{
    create_grid_slot_or_none,
    create_reproducible_slot_with_fields,
    pad_coordinates_randomly,
    pad_grid_randomly,
    random_vacancy_policy,
    RANDOM_USIZE,
};
use crate::tiling::tiles::tile_list::TileList;
use crate::tiling::tiles::{ArrayInitializable, TileConnectionArray};
use crate::tiling::{Direction, GridSlot, SlotGrid, VacancyPolicy};

// noinspection DuplicatedCode
#[rstest]
// region the current slot is None, false
#[case::the_current_slot_is_none_false(
    (3, 3),
    array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (3, 3),
    *RANDOM_PREDECESSOR,
    array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region the predecessor does not exist, panic
#[should_panic(expected = "the predecessor should be Some(GridSlot)")]
#[case::the_predecessor_does_not_exist_panic(
    pad_coordinates_randomly((3, 3)),
    pad_grid_randomly(
        array![
            [None, None, None, None, None, None],
            [
                None,
                None,
                None,
                None,
                None,
                None,
            ],
            [
                None,
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
            ],
            [
                None,
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_reproducible_slot_with_fields(
                    None,
                    Some((1, rand_usize(1, 6))),
                    vec![],
                ),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
            ],
            [
                None,
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
            ],
            [
                None,
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
                create_grid_slot_or_none(),
            ],
        ]
    ),
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (3, 3),
    *RANDOM_PREDECESSOR,
    array![[]],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region direction north, small, false
#[case::direction_north_small_false(
    (3, 3),
    array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::North),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
            None,
        ],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (2, 3),
    Some((3, 3)),
    array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::North),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
            None,
        ],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region direction north, false
#[case::direction_north_false(
    (3, 5),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::North),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (2, 5),
    Some((3, 5)),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::North),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region direction east, false
#[case::direction_east_false(
    (3, 5),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::East),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (3, 6),
    Some((3, 5)),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::East),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region direction south, false
#[case::direction_south_false(
    (3, 5),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::South),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (4, 5),
    Some((3, 5)),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::South),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region direction west, false
#[case::direction_west_false(
    (3, 5),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (3, 4),
    Some((3, 5)),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region direction west, alternative, false
#[case::direction_west_alternative_false(
    (3, 5),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![],
    false,
    (3, 4),
    Some((3, 5)),
    array![
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None],
    ],
    vec![],
)]
// endregion
// region direction west, large, false
#[case::direction_west_large_false(
    (4, 6),
    array![
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (4, 5),
    Some((4, 6)),
    array![
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::West),
                *RANDOM_PREDECESSOR,
                vec![],
            ),
            None,
        ],
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
        [None, None, None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region dead-end with successors, one hop, not first reached, false
#[case::dead_end_with_successors_one_hop_not_first_reached_false(
    (3, 3),
    array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::East),
                *RANDOM_PREDECESSOR,
                vec![Direction::North],
            ),
            create_reproducible_slot_with_fields(None, Some((3, 2)), vec![]),
            create_reproducible_slot_with_fields(None, Some((3, 3)), vec![]),
            None,
        ],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ],
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
    false,
    (2, 2),
    Some((3, 2)),
    array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [
            None,
            None,
            create_reproducible_slot_with_fields(
                Some(Direction::North),
                *RANDOM_PREDECESSOR,
                vec![Direction::North],
            ),
            create_reproducible_slot_with_fields(None, Some((3, 2)), vec![]),
            create_reproducible_slot_with_fields(None, Some((3, 3)), vec![]),
            None,
        ],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ],
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE + 3)],
)]
// endregion
// region dead-end with successors, one hop, not first reached, alternative, false
#[case::dead_end_with_successors_one_hop_not_first_reached_alternative_false(
    (*RANDOM_USIZE + 3, *RANDOM_USIZE * 2 + 3),
    pad_grid_randomly(
        array![
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::East),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::North],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 5, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 3, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                None,
            ],
            [None, None, None, None, None, None],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::East],
                ),
                None,
                None,
            ],
        ]
    ),
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE * 2 + 3)],
    false,
    (*RANDOM_USIZE + 5, *RANDOM_USIZE * 2 + 4),
    Some((*RANDOM_USIZE + 5, *RANDOM_USIZE * 2 + 3)),
    pad_grid_randomly(
        array![
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::East),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::North],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 5, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 3, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                None,
            ],
            [None, None, None, None, None, None],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::East),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::East],
                ),
                None,
                None,
            ],
        ]
    ),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE * 2 + 3)],
)]
// endregion
// region dead-end without successors, three hops, not first reached, false
#[case::dead_end_without_successors_three_hops_not_first_reached_false(
    (*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 3),
    pad_grid_randomly(
        array![
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::East),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::North],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                None,
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 5)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    Some((*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 5)),
                    vec![Direction::South],
                ),
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::East],
                ),
                None,
                None,
            ],
        ]
    ),
    random_vacancy_policy(),
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE * 2 + 3)],
    false,
    (*RANDOM_USIZE + 8, *RANDOM_USIZE * 2 + 5),
    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 5)),
    pad_grid_randomly(
        array![
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::East),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::North],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                None,
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 5)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    Some((*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 5)),
                    vec![Direction::South],
                ),
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::East],
                ),
                None,
                None,
            ],
        ]
    ),
    vec![
        (*RANDOM_USIZE + 4, *RANDOM_USIZE * 2 + 3),
        (*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 3),
    ],
)]
// endregion
// region dead-end without successors, two hops, first reached, true
#[case::dead_end_without_successors_two_hops_first_reached_true(
    (*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 3),
    pad_grid_randomly(
        array![
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::East),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::North],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                None,
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(None, None, vec![]),
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    Some((*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 5)),
                    vec![Direction::South],
                ),
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::East],
                ),
                None,
                None,
            ],
        ]
    ),
    VacancyPolicy::Ignore,
    vec![(*RANDOM_USIZE + 4, *RANDOM_USIZE * 2 + 3)],
    true,
    (*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4),
    None,
    pad_grid_randomly(
        array![
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [None, None, None, None, None, None],
            [
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::East),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::North],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 3)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                None,
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    None,
                    Some((*RANDOM_USIZE + 7, *RANDOM_USIZE * 2 + 4)),
                    vec![],
                ),
                create_reproducible_slot_with_fields(None, None, vec![]),
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    Some((*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 5)),
                    vec![Direction::South],
                ),
            ],
            [
                None,
                None,
                None,
                create_reproducible_slot_with_fields(
                    Some(Direction::South),
                    *RANDOM_PREDECESSOR,
                    vec![Direction::East],
                ),
                None,
                None,
            ],
        ]
    ),
    vec![
        (*RANDOM_USIZE + 4, *RANDOM_USIZE * 2 + 3),
        (*RANDOM_USIZE + 6, *RANDOM_USIZE * 2 + 3),
    ],
)]
// endregion
fn test_prepare_next_iteration(
    #[case] current_slot: (usize, usize),
    #[case] grid: Array2<Option<GridSlot>>,
    #[case] vacancy_policy: VacancyPolicy,
    #[case] last_leaves: Vec<(usize, usize)>,
    #[case] expected_result: bool,
    #[case] expected_current_slot: (usize, usize),
    #[case] expected_current_predecessor: Option<(usize, usize)>,
    #[case] expected_grid: Array2<Option<GridSlot>>,
    #[case] expected_last_leaves: Vec<(usize, usize)>,
) {
    let tile_list = TileList {
        tiles: vec![],
        horizontal_connector_names: vec![],
        vertical_connector_names: vec![],
        tile_type: random_tile_type(),
    };
    let mut slot_grid = SlotGrid {
        num_rows: grid.nrows() - 1,
        num_cols: grid.ncols() - 1,
        grid,
        border_tile_id: Some(rand_usize(0, 11)),
        tile_connections: TileConnectionArray::new(&tile_list.tiles),
        tile_list,
        missing_tile_policy: random_missing_tile_policy(),
        tile_selection_policy: random_tile_selection_policy(),
        vacancy_policy,
        current_slot,
        current_predecessor: *RANDOM_PREDECESSOR,
        last_leaves,
        exposed_edge_count: rand_usize(1, 15),
    };

    let result = slot_grid.prepare_next_iteration();

    assert_eq!(result, expected_result);
    assert_eq!(slot_grid.current_slot, expected_current_slot);
    assert_eq!(slot_grid.current_predecessor, expected_current_predecessor);
    assert_eq!(slot_grid.grid, expected_grid);
    assert_eq!(slot_grid.last_leaves, expected_last_leaves);
}
